/********************************************************************
  Copyright: 2011 Alexander Sokoloff <sokoloff.a@gmail.ru>

  This program is free software; you can redistribute it and/or
  modify it under the terms of the GNU General Public License.
  version 2 as published by the Free Software Foundation.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program; if not, write to the Free Software Foundation,
  Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

*********************************************************************/

#include "trayicon.h"

#include <QtGui/QMenu>
#include <QDebug>
#include <QtGui/QApplication>
#include <QtCore/QProcess>
#include <QStringList>
#include <QtCore/QFileInfo>
#include <QtCore/QDir>
#include <QRegExp>
#include "playlists.h"

#define CFG_LASTURL_KEY     "main/LastUrl"
#define CFG_LASTTITLE_KEY   "main/LastTitle"

/************************************************

 ************************************************/
TrayIcon::TrayIcon(QObject *parent)
    : QSystemTrayIcon(parent),
    mSettings("radiola", "config"),
    mBitrate(0)
{
    connect(&mPlayer, SIGNAL(readyRead()), this, SLOT(dataReady()));
    connect(&mPlayer, SIGNAL(stateChanged(QProcess::ProcessState)), this, SLOT(playerStateChanged(QProcess::ProcessState)));

    connect(this, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), this, SLOT(clicked(QSystemTrayIcon::ActivationReason)));

    mIconOn = QIcon(":/icons/radiola_on.png");
    mIconOff = QIcon(":/icons/radiola_off.png");
    setIcon(mIconOff);


    mUrl = mSettings.value(CFG_LASTURL_KEY).toString();
    mTitle = mSettings.value(CFG_LASTTITLE_KEY).toString();
}


/************************************************

 ************************************************/
TrayIcon::~TrayIcon()
{
    stop();
    mSettings.setValue(CFG_LASTURL_KEY, mUrl);
    mSettings.setValue(CFG_LASTTITLE_KEY, mTitle);
}


/************************************************

 ************************************************/
void TrayIcon::clicked(QSystemTrayIcon::ActivationReason reason)
{
    switch (reason)
    {
        //case QSystemTrayIcon::Trigger:
        case QSystemTrayIcon::MiddleClick:
        case QSystemTrayIcon::Context:
            showMenu();
            break;

        case QSystemTrayIcon::Trigger:
        //case QSystemTrayIcon::Context:
        //case QSystemTrayIcon::MiddleClick:
            playStop();
            break;

        default:
            break;
    }
}


/************************************************

 ************************************************/
void TrayIcon::playStop()
{
    if (isPlaying())
        stop();
    else
        play();
}


/************************************************

 ************************************************/
void TrayIcon::showMenu()
{
    QMenu menu;
    QAction* act;

    if (isPlaying())
    {
        act = menu.addAction(QIcon::fromTheme("media-playback-stop"), tr("Stop"));
        connect(act, SIGNAL(triggered()), this, SLOT(stop()));
    }
    else
    {
        act = menu.addAction(QIcon::fromTheme("media-playback-start"), tr("Play"));
        connect(act, SIGNAL(triggered()), this, SLOT(play()));
    }


    QMenu* stationMenu = menu.addMenu(QIcon::fromTheme("applications-internet"), tr("Stations"));
    QActionGroup* actGroup = new QActionGroup(&menu);

    QString playListFile = QString("%1/playlist.pls").arg(QFileInfo(mSettings.fileName()).dir().path());
    PlayList* playList = new PlsPlayList(playListFile);
    playList->doLoad();

    for (int i=0; i<playList->count(); ++i)
    {
        const StationInfo* si = playList->at(i);
        act = actGroup->addAction(si->title());
        act->setData(si->url());
        act->setCheckable(true);
        stationMenu->addAction(act);
        act->setChecked(mUrl == si->url());
        connect(act, SIGNAL(triggered()), this, SLOT(changeStation()));
    }

    menu.addSeparator();

    act = menu.addAction(tr("Exit"));
    connect(act, SIGNAL(triggered()), qApp, SLOT(quit()));
    menu.exec(QCursor::pos());
}


/************************************************

 ************************************************/
void TrayIcon::changeStation()
{
    QAction* act = qobject_cast<QAction*>(sender());
    if (!act)
        return;

    mTitle = act->text();
    mUrl = act->data().toString();
    play();
}


/************************************************
 -softvol
    Force the use of the software mixer, instead of using the sound card mixer.

 -softvol-max <10.0-10000.0>
    Set the maximum amplification level in percent (default: 110).  A value of 200 will allow you to adjust the volume  up  to  a
    maximum  of  double  the  current level.  With values below 100 the initial volume (which is 100%) will be above the maximum,
    which e.g. the OSD cannot display correctly.

 -volstep <0-100>
    Set the step size of mixer volume changes in percent of the whole range (default: 3).

 -volume <-1-100> (also see -af volume)
    Set the startup volume in the mixer, either hardware or software (if used with -softvol).  A value of -1 (the  default)  will
    not change the volume.
 ************************************************/
void TrayIcon::play()
{
    stop();

    QStringList args;
    args << "-msgmodule";
    args << "-msglevel" << "identify=4:statusline=0";
    //args << "-softvol";
    //args << "-softvol-max" << "110.0";
    //args << "-volstep" << "1";
    //args << "-volume" << "100";
    args << mUrl;



    mPlayer.start("mplayer", args);
    if (!mPlayer.waitForStarted())
        return;
}


/************************************************

 ************************************************/
void TrayIcon::stop()
{
    if (isPlaying())
    {
        mPlayer.terminate();
        mPlayer.waitForFinished();
    }
}


/************************************************

 ************************************************/
void TrayIcon::dataReady()
{
    QStringList lines = QString(mPlayer.readAll()).split('\n');

    QRegExp bitrateRe("\\s*IDENTIFY: ID_AUDIO_BITRATE=(\\d+).*");

    foreach(QString line, lines)
    {
        qDebug() << line;
        if (line.startsWith("ICY Info:"))
        {
            qDebug() << line;
            int b = line.indexOf("StreamTitle=");
            if (b < 0)
                continue;

            b += 13;
            int e = line.indexOf("';", b);
            if (e < 0)
                continue;

            setTrackInfo(line.mid(b, e-b));
        }

        // Bitrate ....................
        if (bitrateRe.exactMatch(line))
        {
            mBitrate = bitrateRe.cap(1).toInt();
        }

    }
}


/************************************************

 ************************************************/
void TrayIcon::playerStateChanged(QProcess::ProcessState newState)
{
    switch (newState)
    {
        case QProcess::NotRunning:
            setIcon(mIconOff);
            setTrackInfo("");
            break;

        case QProcess::Starting:
        case QProcess::Running:
           setIcon(mIconOn);
           updateToolTip();
           break;
    }
}


/************************************************

 ************************************************/
bool TrayIcon::isPlaying()
{
    return  !(QProcess::NotRunning == mPlayer.state());
}


/************************************************

 ************************************************/
void TrayIcon::setTrackInfo(const QString& trackInfo)
{
    mTrackInfo = trackInfo;
    updateToolTip();
}


/************************************************

 ************************************************/
QString bitsTo(int bits)
{
    if (bits > 1000000)
        return QObject::tr("%1 Mbit/s").arg(bits / 1000000, 3);

    if (bits > 1000)
         return QObject::tr("%1 Kbit/s").arg(bits / 1000, 3);

    else
        return QObject::tr("%1 bit/s").arg(bits);
}


/************************************************

 ************************************************/
void TrayIcon::updateToolTip()
{
    QString toolTip;
    if (isPlaying())
    {
        toolTip = "<nobr>" +
                  tr("<b>%1</b><hr>\n"
                      "%2<br>\n"
                      "<font size=-1><i>%3</i></font>"
                    ) + "</nobr>";
        setToolTip(toolTip.arg(mTrackInfo, mTitle, bitsTo(mBitrate)));
    }
    else
    {
        toolTip = "<nobr>%2</nobr>";
        setToolTip(toolTip.arg(mTitle));
    }
}


/************************************************

 ************************************************/
bool TrayIcon::event(QEvent* e)
{
    if (e->type() == QEvent::ToolTip)
    {
        updateToolTip();
    }

    return QSystemTrayIcon::event(e);
}
